package com.jeronimo.eko.core.beans;

import static org.junit.Assert.assertEquals;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Injector;

import edu.umd.cs.findbugs.annotations.SuppressWarnings;

public class BeanCodecTest1 {

	@SuppressWarnings(value={"UwF"})
	ISBeanCodec beanCodec;
	
    public static void main(String arg[]) {
    	try {
        	BeanCodecTest1 inst = new BeanCodecTest1();
        	inst.start();
        	//inst.test1();
        	inst.testInterface1();
    	} catch (Throwable t) {
    		t.printStackTrace();
    	}
    }

    @Before
	@SuppressWarnings("SIC")
    public void start() throws Exception {
    	if (beanCodec==null) {
    		Injector injector = Guice.createInjector(new AbstractModule() {
				@Override protected void configure() {
					
				}
    		});
    		beanCodec = injector.getInstance(ISBeanCodec.class);
    	}
    }
    
    @After
    public void stop() throws Exception {
    }
    
    @Test
    public void test1() throws Exception {
    	BeanTest2 test = new BeanTest2();
    	test.initTest1();
    	testEncoder(test);
    }
    
    @Test
    public void test2() throws Exception {
    	BeanTest2 test = new BeanTest2();
    	test.initTest2();
    	testEncoder(test);
    }
    
    @Test(expected=ClassNotEncodableException.class)
    public void testUidClash() throws Exception {
    	test2();
    	//first test so the bean is registered for sure
    	beanCodec.registerBeanClass(ClashUidBean.class);
    }
    
    @Test
    public void testPredefinedSizeOk() throws Exception {
    	BeanTest3 test3 = new BeanTest3();
    	test3.initTest1();
    	testEncoder(test3);
    	test3.initTest2();
    	testEncoder(test3);
    }

    @Test
    public void testEmptyBean() throws Exception {
    	TestEmptyBean toEncode = new TestEmptyBean();
    	testEncoder(toEncode);
    }

    @Test(expected=EncodingException.class)
    public void testEnumNull() throws Exception {
    	BeanTestEnum testEnum = new BeanTestEnum();
    	testEnum.initTest1();
    	testEnum.setEnum1(null);
    	testEncoder(testEnum);
    }

    @Test(expected=EncodingException.class)
    public void testEnumNull2() throws Exception {
    	BeanTestEnum testEnum = new BeanTestEnum();
    	testEnum.initTest1();
    	testEnum.setEnumArray(new BeanTestEnum.TestEnum[] {null});
    	testEncoder(testEnum);
    }
    

    @Test()
    public void testInterface1() throws Exception {
    	if (beanCodec.getPropertiesDescriptor(BeanTestInterface2.class)==null) {
    		beanCodec.registerBeanClass(BeanTestInterface2.class);// for dynamic beans, registering the encompassing bean is not enough
    	}	
    	if (beanCodec.getPropertiesDescriptor(BeanTestInterface3.class)==null) {
    		beanCodec.registerBeanClass(BeanTestInterface3.class);
    	}
    	BeanTestInterface1 bean = new BeanTestInterface1();
    	bean.initTest1();
    	testEncoder(bean);
    }
    
    
    
	@Encodable (messageClassId = 133,versionId=1)
	public class ClashUidBean {

	}

    
    public void testEncoder(Object toEncode) throws Exception {
    	if (beanCodec.getPropertiesDescriptor(toEncode.getClass())==null) {
    		beanCodec.registerBeanClass(toEncode.getClass());
    	}
    	BeanPropertiesDescriptor descriptor = beanCodec.getPropertiesDescriptor(toEncode.getClass());
    	EncodedBean encoded = beanCodec.encodeBean(toEncode);
    	System.out.println("encoded bean test, buffer="+encoded.getDatas().limit()+" bytes, size="+encoded.getSize());
    	//assert size are correct
    	assertEquals("size test between buffer and encoded.getSize for bean="+toEncode,encoded.getDatas().limit(),encoded.getSize());
    	
    	int precomputedSize = descriptor.getSizeIfPossible();
    	
    	if (encoded.isFixedSize()==false) {
    		assertEquals("precomputed size is -1", -1,precomputedSize);
    	} else {
    		assertEquals("precomputed size is not correct", encoded.getSize(),precomputedSize);
    	}
    	Object decoded = beanCodec.decodeBean(encoded);
    	assertEquals("decoded bean and source bean matches for "+toEncode,toEncode,decoded);
    	System.out.println("test passed for "+toEncode);
    }
}
